package com.yk.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yk.api.dataGatherer.dto.DeviceMigrateDTO;
import com.yk.api.system.dto.GatewayDTO;
import com.yk.common.core.constant.CacheConstants;
import com.yk.common.core.constant.NumberConstant;
import com.yk.common.core.domain.BasePageQuery;
import com.yk.common.core.domain.LoginUser;
import com.yk.common.core.exception.ServiceException;
import com.yk.common.core.utils.LoginHelper;
import com.yk.common.rabbitmq.constant.QueueConstants;
import com.yk.common.redis.service.RedisService;
import com.yk.system.convert.GatewayConvert;
import com.yk.system.entity.*;
import com.yk.system.mapper.*;
import com.yk.system.service.GatewayService;
import com.yk.system.service.MessageService;
import com.yk.system.service.TemplateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * @author lmx
 * @date 2023/10/24 9:45
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GatewayServiceImpl extends ServiceImpl<GatewayMapper, Gateway> implements GatewayService {

    private final GatewayConvert gatewayConvert;
    private final RedisService redisService;
    private final DeviceMapper deviceMapper;
    private final DeviceRoleMapper deviceRoleMapper;
    private final UserMapper userMapper;
    private final TemplateService templateService;
    private final VariableMapper variableMapper;
    private final VariableTemplateMapper variableTemplateMapper;
    private final MessageService messageService;
    private final AmqpTemplate amqpTemplate;

    @Override
    public int updateBatch(List<Gateway> list) {
        return baseMapper.updateBatch(list);
    }

    @Override
    public int batchInsert(List<Gateway> list) {
        return baseMapper.batchInsert(list);
    }

    @Override
    public IPage<Gateway> queryPage(BasePageQuery<GatewayDTO> pageParam) {
        return baseMapper.queryPage(new Page<>(pageParam.getPageNum(), pageParam.getPageSize()), pageParam.getParam());
    }

    @Override
    public void initGateway() {
        List<Gateway> gateways = baseMapper.selectList(new LambdaQueryWrapper<>());
        if (CollUtil.isEmpty(gateways)) {
            return;
        }
        gateways.forEach(it -> {
            GatewayDTO gatewayDTO = gatewayConvert.entity2Dto(it);
            redisService.setCacheObject(CacheConstants.GATEWAY_KEY + gatewayDTO.getTopic(), gatewayDTO);
        });
    }

    @Override
    public Integer getPageNum(Long id, Long pageSize) {
        Long userId = LoginHelper.getLoginUserId();
        String pageNum = baseMapper.getPageNum(id, pageSize, userId);
        BigDecimal number = new BigDecimal(pageNum);
        return number.intValue();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(Long id, String phone) throws Exception {
        Gateway gateway = baseMapper.selectById(id);
        if (Objects.isNull(gateway)) {
            throw new ServiceException("网关不存在");
        }
        User user = userMapper.selectUserByPhone(phone);
        if (Objects.isNull(user)) {
            throw new ServiceException("接收人不存在");
        }
        Long userId = user.getId();
        List<Template> ts = CollUtil.newArrayList();
        List<Variable> vs = CollUtil.newArrayList();
        List<VariableTemplate> vts = Lists.newArrayList();
        List<DeviceRole> ds = Lists.newArrayList();
        // 关联设备
        List<Device> deviceList = deviceMapper.selectList(new LambdaQueryWrapper<Device>().eq(Device::getGatewayId, id));
        if (CollUtil.isEmpty(deviceList)) {
            gateway.setCreatedBy(userId);
            baseMapper.updateById(gateway);
        }
        for (Device it : deviceList) {
            // 设备权限
            List<DeviceRole> rs = deviceRoleMapper.selectByDeviceId(it.getId());
            if (CollUtil.isNotEmpty(rs)) {
                rs.forEach(r -> {
                    if (r.getUserId().equals(userId)) {
                        deviceRoleMapper.deleteById(r.getId());
                    } else if (r.getUserId().equals(it.getCreatedBy())) {
                        r.setAdminId(userId);
                        r.setUserId(userId);
                        ds.add(r);
                    } else {
                        r.setAdminId(userId);
                        ds.add(r);
                    }
                });
            }
            it.setCreatedBy(userId);
            // 模板
            if (Objects.isNull(it.getTemplateId())) {
                break;
            }
            Template template = templateService.getById(it.getTemplateId());
            Long oldTemplateId = template.getId();
            template.setId(IdWorker.getId());
            template.setCreatedBy(userId);
            ts.add(template);
            // 变量
            List<Variable> vbs = variableMapper.queryByTemplateId(it.getTemplateId());
            it.setTemplateId(template.getId());
            if (CollUtil.isEmpty(vbs)) {
                break;
            }
            vbs.forEach(variable -> {
                variable.setId(IdWorker.getId());
                variable.setCreatedBy(userId);
                vs.add(variable);
                vts.add(new VariableTemplate(variable.getId(), template.getId()));
            });
            deviceMapper.updateById(it);
            // 创建超级表并缓存
            templateService.createSuperTableAndCache(template.getId(), vbs);
            // 设备数据迁移
            DeviceMigrateDTO deviceMigrateDTO = new DeviceMigrateDTO(it.getId(), template.getId(), oldTemplateId);
            try {
                amqpTemplate.convertAndSend(QueueConstants.DEVICE_MIGRATE, deviceMigrateDTO);
            }catch (Exception e){
                log.error("网关数据迁移失败", e.getMessage());
                throw new ServiceException("网关数据迁移失败");
            }
        }
        // 转移
        gateway.setCreatedBy(userId);
        baseMapper.updateById(gateway);
        if (CollUtil.isNotEmpty(deviceList)) {
            deviceMapper.updateBatch(deviceList);
        }
        if (CollUtil.isNotEmpty(ds)) {
            deviceRoleMapper.updateBatch(ds);
        }
        if (CollUtil.isNotEmpty(ts)) {
            templateService.batchInsert(ts);
        }
        if (CollUtil.isNotEmpty(vs)) {
            variableMapper.batchInsert(vs);
        }
        if (CollUtil.isNotEmpty(vts)) {
            variableTemplateMapper.batchInsert(vts);
        }
        // 发送系统通知
        LoginUser loginUser = LoginHelper.getLoginUser();
        String message = loginUser.getNickname() + "给您转让网关：" + gateway.getName();
        messageService.systemMessage("网关转让通知", userId, message, NumberConstant.ZERO_STR);
    }

    @Override
    public List<Gateway> getByUserId(Long userId) {
        LambdaQueryWrapper<Gateway> lambda = new LambdaQueryWrapper<>();
        lambda.eq(Gateway::getCreatedBy, userId);
        return baseMapper.selectList(lambda);
    }
}
